package main

import (
	"errors"
	"log"
	"net"
	"net/http"
	"net/rpc"

	"fmt"
	"time"
)

func init() {
	fmt.Println("init rpc")
}

type MyArgs struct {
	A, B int
}

type Quotient struct {
	Quo, Rem int
}

type Arith int

func (arith *Arith) Multiply(args *MyArgs, reply *int) error {
	time.Sleep(2 * time.Second) //默认是纳秒

	*reply = args.A * args.B
	return nil
}

func (arith *Arith) Divide(args *MyArgs, quotient *Quotient) error {
	if args.B == 0 {
		return errors.New("divide by zero")
	}

	time.Sleep(2 * time.Second)

	quotient.Quo = args.A / args.B
	quotient.Rem = args.A % args.B
	return nil
}

func Server_demo() {
	//arith0 := Arith(0) //arith0是实例

	arith := new(Arith) //arith是指针

	rpc.Register(arith) //注册了Arith的其公共方法
	rpc.HandleHTTP()    //registers an HTTP handler
	listener, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("listen error:", err)
	}

	//accepts incoming HTTP connections on the listener l, creating a new service goroutine for each
	//Handler is nil, in which case the DefaultServeMux is used.
	go http.Serve(listener, nil)

}

//默认采用Gob（只针对Go语言）来二进制序列化
func Client_demo_sync() {
	client, err := rpc.DialHTTP("tcp", ":1234")
	if err != nil {
		log.Fatal("dial error: ", err)
	}

	args := &MyArgs{9, 8}
	var reply int
	//同步调用
	err = client.Call("Arith.Multiply", args, &reply)
	if err != nil {
		log.Fatal("call error: ", err)
	}

	log.Println("reply: ", reply)

}

func Client_demo_async() {
	client, err := rpc.DialHTTP("tcp", ":1234")
	if err != nil {
		log.Fatal("dial error: ", err)
	}

	args := &MyArgs{9, 8}
	var reply Quotient
	//异步调用  //If done is nil, Go will allocate a new channel.
	call := client.Go("Arith.Divide", args, &reply, nil)

	log.Println("do something")

	log.Println("reply: ", (<-call.Done).Reply) //channel block

}

func main() {
	Server_demo()

	//Client_demo_sync()

	Client_demo_async()

}
